package jp.ac.waseda.cs.washi.game;

import jp.ac.waseda.cs.washi.game.api.PumpkinType;
import jp.ac.waseda.cs.washi.game.entity.Chara;
import jp.ac.waseda.cs.washi.game.entity.Map;
import jp.ac.waseda.cs.washi.game.entity.Pumpkin;
import jp.ac.waseda.cs.washi.game.entity.PumpkinCore;
import jp.ac.waseda.cs.washi.game.entity.Tile;
import jp.ac.waseda.cs.washi.gameaiarena.api.Point2;

public final class MagicManager {
	private MagicManager() {
	}

	// 指定された地点がボーナス図形のコアだった場合、そのボーナス図形(かぼちゃ)のコアを返す
	public static PumpkinCore getPumpkinCore(Chara owner, Point2 coreLocation) {
		Pumpkin pumpkin = getPumpkin(owner, coreLocation);
		if (pumpkin == null)
			return null;
		return pumpkin.getCore(coreLocation);
	}

	// 指定された地点がボーナス図形のコアだった場合、そのボーナス図形(かぼちゃ)を返す
	public static Pumpkin getPumpkin(Chara owner, Point2 coreLocation) {
		if (owner == null)
			return null;
		for (Pumpkin pump : owner.getPumpkins()) {
			for (PumpkinCore core : pump.getCores()) {
				Point2 dp = core.getLocation();
				if (dp.equals(coreLocation))
					return pump;
			}
		}
		return null;
	}

	// キャラクタが魔方陣を描く行動を選択した際のマップへの影響を計算する
	public static void spell(Map map, Chara speller) {
		Point2 p = speller.getLocation(); // キャラクタの位置座標
		for (Point2 spellPoint : speller.getMassSpellType().getSpellPoints()) {
			Point2 mapLocation = new Point2(p.x + spellPoint.x, p.y
					+ spellPoint.y);
			Tile tile = map.getTile(mapLocation);
			spellAt(map, speller, mapLocation, tile);
		}
	}

	private static void spellAt(Map map, Chara speller, Point2 p, Tile tile) {
		// 魔法陣を描けるかどうか。描けない場合は何も起こらない。
		// ※ボーナス図形の中心点以外はロックされるルールになってます
		if (!tile.canDevelop()) {
			return;
		}
		Chara owner = tile.getCompleteOwner();
		Chara incompleateOwner = tile.getOwner();
		if ((owner != null && owner != speller)||(incompleateOwner != null && incompleateOwner != speller)) {
			// 足元のタイルは敵が描いた(途中の)魔方陣の場合
			Pumpkin pump = getPumpkin(owner, p);
			if (pump != null) {
				PumpkinCore core = pump.getCore(p);
				if (core != null) {
					developEnemyPumpkinCore(speller, tile, owner, pump, map,
							core);
					return;
				}
			}
			/*
			 * // 敵のマスがかぼちゃの場合 if (pump != null) { developEnemyPumpkin(speller,
			 * tile, owner, pump, map); return; }
			 */
			// 敵のマスがかぼちゃでない場合
			developEnemyTile(speller, tile);
			return;
		}
		developMyOrPlainTile(speller, tile, map);
	}

	private static void developEnemyPumpkinCore(Chara speller, Tile tile,
			Chara enemy, Pumpkin pump, Map map, PumpkinCore core) {
		core.decrementDurability();
		// かぼちゃを破壊した場合は(pump.getDurability()==0)破壊ボーナスを加算する
		if (core.getStrength() <= 0) {
			speller.addBreakScore();
			pump.removeCore(core);
			if (pump.getCores().size() == 0) {
				// enemy.getPumpkins().remove(pump);
				Point2[] dps = { new Point2(1, 0), new Point2(0, 1),
						new Point2(-1, 0), new Point2(0, -1) };

				Point2 center = pump.getCenterLocation();
				for (Point2 dp : dps) {
					map.getTile(center.add(dp)).setStrength(0);
					map.getTile(center.add(dp)).setIncompleteOwner(null);
					map.getTile(center.add(dp)).setOwner(null);
				}
				if (pump.getType() == PumpkinType.KingPumpkin) {
					for (Point2 dp : dps) {
						Point2 p = center.add(dp);
						for (Point2 dpp : dps) {
							map.getTile(p.add(dpp)).setStrength(0);
							map.getTile(p.add(dpp)).setIncompleteOwner(null);
							map.getTile(p.add(dpp)).setOwner(null);
						}
					}
				}
			}

			// tile.setIncompleteOwner(null);
			// tile.setOwner(null);
			// tile.setStrength(0);
		}
	}

	private static void developEnemyTile(Chara speller, Tile tile) {
		// キャラクタの足元のタイルの完成度を取得する
		int level = tile.getStrength();
		// 敵のタイルだったとき、その強度を DESTROY_STRENGTH 分だけ減少させる
		level = level - Settings.DESTROY_STRENGTH;
		// 強度が0になったら、タイルは初期状態に戻る
		if (level <= 0) {
			tile.setIncompleteOwner(null);
			level = 0;
		}
		tile.setOwner(null);
		tile.setStrength(level);
	}

	private static void developMyOrPlainTile(Chara speller, Tile tile, Map map) {
		boolean isComplete = false; // 今回のspellによって、魔方陣が完成したかどうかを示すフラグ
		int level = tile.getStrength();
		// 魔方陣が完成した場合はタイルの強度(level)を規定値まで上昇させる
		level += Settings.DEVELOP_STRENGTH;
		if (level >= Settings.COMPLETE_STRENGTH) {
			// 魔方陣が完成したら Ownerになれる
			tile.setOwner(speller);
			level = Settings.COMPLETE_STRENGTH;
			isComplete = true;
		}
		tile.setIncompleteOwner(speller);
		tile.setStrength(level);

		// 魔方陣が完成した場合は、塗りつぶし(メテオ)についての処理を行う
		if (isComplete)
			MapManager.invokeMeteor(map, speller.getLocation());
	}

	// キャラクタが魔方陣を消す行動を選択した際のマップへの影響を計算する
	static void clear(Map map, Chara chara) {
		Point2 p = chara.getLocation();
		Tile tile = map.getTile(p);
		// 足元のタイルが自分の魔方陣(作り途中でも)の場合は、タイルの所有者がなくなる
		if (tile.getOwner() == chara) {
			tile.clear(chara);
		}
	}

}